package bme.andraskindler.treenventory.provider;

import java.util.Timer;
import java.util.TimerTask;

import android.content.Context;
import android.location.Location;
import android.location.LocationListener;
import android.location.LocationManager;
import android.os.Bundle;

/**
 * A pozíció megtalálásáért felelős osztály.
 * 
 * @author andraskindler
 * 
 */
public class MyLocationManager {
	Timer timer;
	LocationManager locationManager;
	LocationResult locationResult;
	boolean GPS_ENABLED = false;
	boolean NETWORK_ENABLED = false;

	/**
	 * A pozíció megtalálásáért felel, megnézi, hogy engedélyezve van-e a GPS vagy a cella alapú pozicionálás, majd ennek megfelelően elindít egy legfeljebb 25 másodperces keresést.
	 * 
	 * @param context
	 * @param result
	 * @return
	 */
	public boolean getLocation(Context context, LocationResult result) {

		locationResult = result;
		if (locationManager == null)
			locationManager = (LocationManager) context.getSystemService(Context.LOCATION_SERVICE);

		try {
			GPS_ENABLED = locationManager.isProviderEnabled(LocationManager.GPS_PROVIDER);
		} catch (Exception e) {
			e.printStackTrace();
		}
		try {
			NETWORK_ENABLED = locationManager.isProviderEnabled(LocationManager.NETWORK_PROVIDER);
		} catch (Exception e) {
			e.printStackTrace();
		}

		if (!GPS_ENABLED && !NETWORK_ENABLED)
			return false;

		if (GPS_ENABLED)
			locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 0, 0, locationListenerGps);
		if (NETWORK_ENABLED)
			locationManager.requestLocationUpdates(LocationManager.NETWORK_PROVIDER, 0, 0, locationListenerNetwork);
		timer = new Timer();
		timer.schedule(new GetLastLocation(), 25000);
		return true;
	}

	LocationListener locationListenerGps = new LocationListener() {

		public void onLocationChanged(Location location) {
			timer.cancel();
			locationResult.gotLocation(location);
			locationManager.removeUpdates(this);
			locationManager.removeUpdates(locationListenerNetwork);
		}

		public void onProviderDisabled(String provider) {
		}

		public void onProviderEnabled(String provider) {
		}

		public void onStatusChanged(String provider, int status, Bundle extras) {
		}

	};

	LocationListener locationListenerNetwork = new LocationListener() {

		public void onLocationChanged(Location location) {
			timer.cancel();
			locationResult.gotLocation(location);
			locationManager.removeUpdates(this);
			locationManager.removeUpdates(locationListenerGps);
		}

		public void onProviderDisabled(String provider) {
		}

		public void onProviderEnabled(String provider) {
		}

		public void onStatusChanged(String provider, int status, Bundle extras) {
		}

	};

	/**
	 * A legutolsó érvényes pozíciót tölti be, amennyiben nem sikerül megtalálni a pozíciót.
	 * 
	 * @author andraskindler
	 * 
	 */
	class GetLastLocation extends TimerTask {
		@Override
		public void run() {
			locationManager.removeUpdates(locationListenerGps);
			locationManager.removeUpdates(locationListenerNetwork);

			Location net_loc = null, gps_loc = null;
			if (GPS_ENABLED)
				gps_loc = locationManager.getLastKnownLocation(LocationManager.GPS_PROVIDER);
			if (NETWORK_ENABLED)
				net_loc = locationManager.getLastKnownLocation(LocationManager.NETWORK_PROVIDER);

			if (gps_loc != null && net_loc != null) {
				if (gps_loc.getTime() > net_loc.getTime())
					locationResult.gotLocation(gps_loc);
				else
					locationResult.gotLocation(net_loc);
				return;
			}

			if (gps_loc != null) {
				locationResult.gotLocation(gps_loc);
				return;
			}
			if (net_loc != null) {
				locationResult.gotLocation(net_loc);
				return;
			}
			locationResult.gotLocation(null);
		}
	}

	public static abstract class LocationResult {
		public abstract void gotLocation(Location location);
	}
}